import apwidgets.*;
import android.content.Context;  
import android.app.Notification;  
import android.app.NotificationManager;  

/**
 * Project Name: Rhythm Touch
 *
 * Filename: project_2_5.pde
 * Author: Terry C. Wong
 * Date: 9/25/12
 * Description:
 *   The Simple Image Browser works like a photo album. It loads all of the images from a specified folder
 * The Simple Image Browser has two display modes: 0 & 1. 
 * Mode 0: A centered bar showing five consecutive images in the image list, as thumbnails, with a selected image being slightly enlarged.
 * Mode 1: A selected image is displayed in the 480 x 854 fullscreen window, with a border of 50 pixels.
 * In both Mode 0 & Mode 1:
 * Users can use LEFT & RIGHT key to toggle the selected image, and UP & DOWN to switch between Mode 0 & Mode 1 for the selected image.
 * Users can also switch between Mode 0 & Mode 1 if they click on the image.
 * Users can flip to the previous/next five consecutive images if they press the LEFT key on the very left image or the RIGHT key on the very right image.
 * Added smooth animation transitions to the flipping of pages.
 * Added Auditory Icons.
 * Added Text Annotations.
 * Users can press the "Show Tags" button to reveal the list of text tags in a text box for a particular picture.
 * Users can append to the list of text tags by entering information in the text field and press <ENTER>.
 * Users can clear the list of text tags by pressing the "Clear Tags" button.
 * Users can hide the list of text tags without saving any changes by pressing the "Hide Tags" button.
 * Users can save the changes made to the list of text tags by pressing the "Save Tags" button.
 * Only in Mode 0:
 * Users can select an image by hovering the mouse over it.
 * Users can also flip to the previous/next five consecutive images if they drag the mouse to the left on the very left image
 * or if they drag the mouse to the right on the very right image.
 * Users can press the ‘<’ or ‘>’ key to flip to the previous/next five consecutive images.
 *
 * Disclaimer: Buttons created with free graphics
 * released under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported license.
 * Source website link: www.mouserunner.net
 */

APMediaPlayer menu_music, menu_pressed, song_music, arrow_pressed, congratz;
PImage tmp, menu_bg, logo, start_base, start_roll, start_down, settings_base, settings_roll, settings_down, rankings_base, rankings_roll, rankings_down;  // Declare variables of type PImage
PImage leftArrow_base, leftArrow_down, downArrow_base, downArrow_down, upArrow_base, upArrow_down, rightArrow_base, rightArrow_down; // PImage variables for Mode 1 buttons and a text box
ArrayList<PImage> bg_images = new ArrayList(); // Declare ArrayList variable of type PImage
PFont myFont;
int mode = 0, previousMode = 0; // Declare the global constant for the border width pixels
int leftArrowIndex = -120, leftArrowMoveIndex = 0, downArrowIndex = -120, downArrowMoveIndex = 0, upArrowIndex = -120, upArrowMoveIndex = 0, rightArrowIndex = -120, rightArrowMoveIndex = 0;
int minMoveRange = 5, maxMoveRange = 15, startTime = 0, elapsedTime = 0;
boolean buttonPressed = false, leftArrowON = false, downArrowON = false, upArrowON = false, rightArrowON = false; // Flags for whether the url background image is loaded and whether mouse locked
String textValue = "";
ImageButton startButton, settingsButton, rankingsButton, leftArrowButton, downArrowButton, upArrowButton, rightArrowButton;
APWidgetContainer widgetContainer; 
APButton quitButton;
APCheckBox soundCheckBox, vibrateCheckBox;
APEditText textField;
// Setup vibration globals
NotificationManager gNotificationManager;
Notification gNotification;
//long[] gVibrate = {0,250,50,125,50,62};
long[] gVibrate = {0, 60};

void setup() {
    orientation(PORTRAIT); // the hamburger way

    try {
      // Open a display window of dimensions 480x854
      menu_bg = loadImage("backgrounds/menu_bg.jpg");
      tmp = loadImage("backgrounds/butterfly_bg.png");
      bg_images.add(tmp);
      tmp = loadImage("backgrounds/hatsune_miku_bg.jpg");
      bg_images.add(tmp);
      //tmp = loadImage("backgrounds/paranoiaRB_bg.jpg");
      //bg_images.add(tmp);
    } catch (Exception e) {
      System.err.println(e.getMessage());
    }
    // print the available system fonts
    //String[] fontList = PFont.list();
    //println(fontList);
    // load the "SansSerif-Bold" system font
    myFont = createFont("SansSerif-Bold", 20, true);
    textFont(myFont);
    // create new APMediaPlayer
    menu_music = new APMediaPlayer(this);
    // set the file (files are in data folder)
    menu_music.setMediaFile("audio/angels in the sky.mp3");
    menu_pressed = new APMediaPlayer(this);
    menu_pressed.setMediaFile("audio/bloop4.wav");
    song_music = new APMediaPlayer(this);
    song_music.setMediaFile("audio/butterfly.mp3");
    arrow_pressed = new APMediaPlayer(this);
    arrow_pressed.setMediaFile("audio/click1.wav");
    congratz = new APMediaPlayer(this);
    congratz.setMediaFile("audio/camera1.wav");
    // Load image files for buttons
    start_base = loadImage("gui/show_tags_active.png");
    start_down = loadImage("gui/show_tags_clicked.png");
    settings_base = loadImage("gui/save_tags_active.png");
    settings_down = loadImage("gui/save_tags_clicked.png");
    rankings_base = loadImage("gui/show_tags_active.png");
    rankings_down = loadImage("gui/show_tags_clicked.png");
    leftArrow_base = loadImage("gui/left_arrow.png");
    leftArrow_down = loadImage("gui/left_arrow.png");
    downArrow_base = loadImage("gui/down_arrow.png");
    downArrow_down = loadImage("gui/down_arrow.png");
    upArrow_base = loadImage("gui/up_arrow.png");
    upArrow_down = loadImage("gui/up_arrow.png");
    downArrow_base = loadImage("gui/down_arrow.png");
    downArrow_down = loadImage("gui/down_arrow.png");
    rightArrow_base = loadImage("gui/right_arrow.png");
    rightArrow_down = loadImage("gui/right_arrow.png");
    // create new image buttons
    startButton = new ImageButton(200, 600, start_base, start_down);
    settingsButton = new ImageButton(200, 660, settings_base, settings_down);
    rankingsButton = new ImageButton(200, 720, rankings_base, rankings_down);
    leftArrowButton = new ImageButton(0, 734, leftArrow_base, leftArrow_down);
    downArrowButton = new ImageButton(120, 734, downArrow_base, downArrow_down);
    upArrowButton = new ImageButton(240, 734, upArrow_base, upArrow_down);
    rightArrowButton = new ImageButton(360, 734, rightArrow_base, rightArrow_down);
    // create new container for widgets
    widgetContainer = new APWidgetContainer(this);
    // create new button from x- and y-pos., width, height and label
    quitButton = new APButton(160, 650, 160, 80, "Quit Game");
    // place button in container
    widgetContainer.addWidget(quitButton);
    soundCheckBox = new APCheckBox(140, 150, " Sound On"); //create new checkbox from x- and y-pos. and label.
    widgetContainer.addWidget(soundCheckBox); //place checkbox in container
    soundCheckBox.setChecked(true); //checkbox is checked from the beginning
    vibrateCheckBox = new APCheckBox(140, 250, " Vibration On"); //create new checkbox from x- and y-pos. and label.
    widgetContainer.addWidget(vibrateCheckBox); //place checkbox in container
    vibrateCheckBox.setChecked(true); //checkbox is checked from the beginning
    //textField = new APEditText(200, 250, 100, 50); //create a textfield from x- and y-pos., width and height
    //widgetContainer.addWidget(textField); //place textField in container
    widgetContainer.hide();
    menu_music.start();
    menu_music.setLooping(true); //restart playback end reached
}

void draw() {
  switch (mode) {
    case 0:
    background(menu_bg);
    fill(0, 255, 0);
    text("Music Duration: " + menu_music.getDuration(), 10, 30); //display the duration of the sound  
    text("Music Position: " + menu_music.getCurrentPosition(), 10, 50); //display how far the sound has played
    text("motionX: " + motionX, 10, 70);
    text("motionY: " + motionY, 10, 90);
    if (startButton.update()) {
      mode = 3;
      buttonPressed = true;
      if (soundCheckBox.isChecked()){
        // "rewind"
        menu_pressed.seekTo(0);
        menu_pressed.start();
        menu_music.pause(); //pause player
        // "rewind"
        song_music.seekTo(0);
        song_music.start();
      }
      startTime = millis();
    }
    startButton.display();
    if (settingsButton.update()) {
      previousMode = 0;
      mode = 1;
      buttonPressed = true;
      menu_music.pause(); //pause player
      widgetContainer.show();
    }
    settingsButton.display();
    if (rankingsButton.update()) {
      mode = 5;
      buttonPressed = true;
      if (soundCheckBox.isChecked()){ 
        menu_music.pause(); //pause player
      }
    }
    rankingsButton.display();
    break;
    case 1:
    background(0);
        
    break;
    case 2:
    background(0, 0, 255);
    
    break;
    case 3:
    background(bg_images.get(0));
    fill(0, 0, 255);
    text("Music Duration: " + song_music.getDuration(), 10, 30); //display the duration of the sound  
    text("Music Position: " + song_music.getCurrentPosition(), 10, 50); //display how far the sound has played
    text("Time elapsed: " + elapsedTime, 10, 70);
    text("motionX: " + motionX, 10, 90);
    text("motionY: " + motionY, 10, 110);
    text("frameCount: " + frameCount, 10, 130);
    text("frameRate: " + frameRate, 10, 150);
    executeGame();
    leftArrowButton.update();
    leftArrowButton.display();
    downArrowButton.update();
    downArrowButton.display();
    upArrowButton.update();
    upArrowButton.display();
    rightArrowButton.update();
    rightArrowButton.display();
    elapsedTime = millis()-startTime;
    if (song_music.getDuration()-song_music.getCurrentPosition() < 100 || song_music.getDuration() <= elapsedTime) {
      mode = 0;
      resetGame();
      if (soundCheckBox.isChecked()){
        song_music.pause(); //pause player
        // "rewind"
        menu_music.seekTo(0);
        menu_music.start();
        menu_music.setLooping(true); //restart playback end reached
      }
    }
    break;
    case 4:

    break;
    case 5:
    background(255);
    
    break;
    default: 
    println("Error: Invalid mode!");
    exit();
    break;
  }
}

// Mode 0 is for drawing five images on the screen for selections
void executeGame() {
  if (frameCount%30 == 0 && song_music.getDuration()-song_music.getCurrentPosition() >= 3500) {
    if (!leftArrowON) {
      if (int(random(50)) != 0) {
        leftArrowMoveIndex = int(random(minMoveRange, maxMoveRange));
        leftArrowON = true;
      }
    }
    if (!downArrowON) {
      if (int(random(50)) != 0) {
        downArrowMoveIndex = int(random(minMoveRange, maxMoveRange));
        println("downArrowMoveIndex: "+downArrowMoveIndex);
        downArrowON = true;
      }
    }
    if (!upArrowON) {
      if (int(random(50)) != 0) {
        upArrowMoveIndex = int(random(minMoveRange, maxMoveRange));
        upArrowON = true;
      }
    }
    if (!rightArrowON) {
      if (int(random(50)) != 0) {
        rightArrowMoveIndex = int(random(minMoveRange, maxMoveRange));
        rightArrowON = true;
      }
    }
  }
  if (leftArrowON || downArrowON || upArrowON || downArrowON) {
    if (leftArrowIndex <= 854) {
      leftArrowIndex += leftArrowMoveIndex;
      //println("leftArrowMoveIndex: "+leftArrowMoveIndex);
      //println("leftArrowIndex: "+leftArrowIndex);
      image(leftArrow_base, 0, leftArrowIndex, leftArrow_base.width, leftArrow_base.height);
    }
    else {
      leftArrowIndex = -120;
      leftArrowMoveIndex = 0;
      leftArrowON = false;
    }
    if (downArrowIndex <= 854 && downArrowMoveIndex != 0) {
      downArrowIndex += downArrowMoveIndex;
      image(downArrow_base, 120, downArrowIndex, downArrow_base.width, downArrow_base.height);
    }
    else {
      downArrowIndex = -120;
      downArrowMoveIndex = 0;
      downArrowON = false;
    }
    if (upArrowIndex <= 854) {
      upArrowIndex += upArrowMoveIndex;
      image(upArrow_base, 240, upArrowIndex, upArrow_base.width, upArrow_base.height);
    }
    else {
      upArrowIndex = -120;
      upArrowMoveIndex = 0;
      upArrowON = false;
    }
    if (rightArrowIndex <= 854) {
      rightArrowIndex += rightArrowMoveIndex;
      image(rightArrow_base, 360, rightArrowIndex, rightArrow_base.width, rightArrow_base.height);
    }
    else {
      rightArrowIndex = -120;
      rightArrowMoveIndex = 0;
      rightArrowON = false;
    }
  }
}

void resetGame() {
  startTime = 0;
  elapsedTime = 0;
  leftArrowIndex = -120;
  leftArrowMoveIndex = 0;
  leftArrowON = false;
  downArrowIndex = -120;
  downArrowMoveIndex = 0;
  rightArrowON = false;
  rightArrowIndex = -120;
  rightArrowMoveIndex = 0;
  rightArrowON = false;
  rightArrowIndex = -120;
  rightArrowMoveIndex = 0;
  rightArrowON = false;
}

// Control and trigger the options when certain keys are pressed
void keyPressed() {
  if (key == CODED) {
    switch (mode) {
      case 0:
      if (keyCode == BACK) {
        exit();
      }
      else if (keyCode == MENU) {
        previousMode = 0;
        mode = 1;
        menu_music.pause(); //pause player
        widgetContainer.show();
      }
      break;
      case 1:
      if (keyCode == BACK) {
        keyCode = 0;
        mode = previousMode;
        motionX = 0;
        motionY = 0;
        widgetContainer.hide();
        if (soundCheckBox.isChecked()){
          if (previousMode == 3) {
            //println("currentPosition: "+song_music.getCurrentPosition());
            //println("elapsedTime: "+elapsedTime);
            song_music.seekTo(elapsedTime+1500); //resume player
            song_music.start();
          }
          else {
            menu_music.start();
          }
        }
      }
      break;
      case 2:
      if (keyCode == BACK) {
        keyCode = 0;
        mode = 0;
        motionX = 0;
        motionY = 0;
      }
      else if (keyCode == MENU) {
        previousMode = 2;
        mode = 1;
        menu_music.pause(); //pause player
        widgetContainer.show();
      }
      break;
      case 3:
      if (keyCode == BACK) {
        keyCode = 0;
        mode = 0;
        resetGame();
        motionX = 0;
        motionY = 0;
        if (soundCheckBox.isChecked()){
          song_music.pause(); //pause player
          // "rewind"
          menu_music.seekTo(0);
          menu_music.start();
          menu_music.setLooping(true); //restart playback end reached
        }      
      }
      else if (keyCode == MENU) {
        previousMode = 3;
        mode = 1;
        if (soundCheckBox.isChecked()){
          song_music.pause(); //pause player
        }
        widgetContainer.show();
      }
      break;
      case 4:
      if (keyCode == BACK) {
        keyCode = 0;
        mode = 0;
        motionX = 0;
        motionY = 0;
        if (soundCheckBox.isChecked()){
          song_music.pause(); //pause player
          // "rewind"
          menu_music.seekTo(0);
          menu_music.start();
          menu_music.setLooping(true); //restart playback end reached
        }
      }
      else if (keyCode == MENU) {
        previousMode = 4;
        mode = 1;
        menu_music.pause(); //pause player
        widgetContainer.show();
      }
      break;
      case 5:
      if (keyCode == BACK) {
        keyCode = 0;
        mode = 0;
        motionX = 0;
        motionY = 0;
        if (soundCheckBox.isChecked()){
          song_music.pause(); //pause player
          // "rewind"
          menu_music.seekTo(0);
          menu_music.start();
          menu_music.setLooping(true); //restart playback end reached
        }
      }
      else if (keyCode == MENU) {
        previousMode = 5;
        mode = 1;
        menu_music.pause(); //pause
        widgetContainer.show();
      }
      break;
      default: 
      println("Error: Invalid mode!");
      exit();
      break;
    }
  }
}

//onClickWidget is called when a widget is clicked/touched
void onClickWidget(APWidget widget){
  // if it was quitButton that was clicked
  if (widget == quitButton) {
    exit();
  }
}

// Override the parent (super) Activity class:  
// States onCreate(), onStart(), and onStop() aren't called by the sketch.  Processing is entered  
// at the 'onResume()' state, and exits at the 'onPause()' state, so just override them as needed
void onResume() {
  super.onResume();
  // Create our Notification Manager
  gNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  // Create our Notification that will do the vibration
  gNotification = new Notification();
  // Set the vibration
  gNotification.vibrate = gVibrate;  
}  

public boolean surfaceTouchEvent(MotionEvent event) {
  text("surfaceTouchEvent triggered!", 10, 170);
  if (vibrateCheckBox.isChecked() && buttonPressed) {
    // If user touches the screen, trigger vibration notification
    gNotificationManager.notify(1, gNotification);
    buttonPressed = false;
  }
  
  // if you want the variables for motionX/motionY, mouseX/mouseY etc.
  // to work properly, you'll need to call super.surfaceTouchEvent().
  return super.surfaceTouchEvent(event);
}

public boolean surfaceKeyDown(int code, KeyEvent event) {
  
  return super.surfaceKeyDown(code, event);
}

public boolean surfaceKeyUp(int code, KeyEvent event) {
  
  return super.surfaceKeyDown(code, event);
}

//The MediaPlayer must be released when the app closes
public void onDestroy() {
 //call onDestroy on super class 
 super.onDestroy(); 
 //must be checked because or else crash when return from landscape mode    
 if (menu_music != null) {
   // release the player
   menu_music.release();
 }
 if (menu_pressed != null) {
   // release the player
   menu_pressed.release();
 }
 if (song_music != null) {
   // release the player
   song_music.release();
 }
 if (arrow_pressed != null) {
   // release the player
   arrow_pressed.release();
 }
 if (congratz != null) {
   // release the player
   congratz.release();
 }
}

class ImageButton
{
  int x, y;
  PImage base, down, currentimage;
  boolean pressed = false;

  ImageButton(int ix, int iy, PImage ibase, PImage idown) 
  {
    x = ix;
    y = iy;
    base = ibase;
    down = idown;
    currentimage = base;
  }
  
  // Return true if button is pressed
  boolean update() 
  {
    pressed();
    if (pressed) {
      currentimage = down;
      return true;
    }
    else {
      currentimage = base;
      return false;
    }
  }
  
  void pressed()
  {
    if (currentimage == base && motionX >= x && motionX <= x+base.width && motionY >= y && motionY <= y+base.height) {
      pressed = true; 
    }      
    else {
      pressed = false;
    }
  }
  
  void display() 
  {
    image(currentimage, x, y);
  }
}

